using System.IO;
using Microsoft.WowAddonStudio.FrameXml.Formats.Tests.Properties;
using NUnit.Framework;
using Microsoft.WowAddonStudio.FrameXml.Formats.Mpq;

namespace Microsoft.WowAddonStudio.FrameXml.Formats.Tests.Mpq
{
    [TestFixture]
    public class MpqArchiveTest
    {
        private const string mpqArchiveRelativePath = @"Data\enGB\base-enGB.MPQ";
        private const string mpqFilePath = @"Data\enGB\Documentation\Manual.pdf";

        private string mpqArchivePath;

        [SetUp]
        public void SetUp()
        {
            if (!Directory.Exists(Settings.Default.WowBasePath))
                Assert.Ignore("Cannot run test. Please set the World of Warcraft base path.");

            mpqArchivePath = Path.Combine(Settings.Default.WowBasePath, mpqArchiveRelativePath);
        }

        [Test]
        public void OpenMpqArchiveTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                Assert.IsTrue(mpqArchive.IsOpen, "Newly created MPQ archive is not open.");
            }
        }

        [Test]
        public void MpqFileTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                using (var mpqFile = mpqArchive.OpenFile(mpqFilePath))
                {
                    Assert.IsNotNull(mpqFile, "OpenFile returned null.");
                    Assert.IsTrue(mpqFile.IsOpen, "Newly opened file is not open.");
                    Assert.AreNotEqual(0, mpqFile.Size, "Opened file has zero size.");
                }
            }
        }

        [Test] 
        public void MpqStreamTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                using (var mpqFile = mpqArchive.OpenFile(mpqFilePath))
                using (var mpqStream = mpqFile.GetStream())
                {
                    Assert.AreEqual(0, mpqStream.Position, "Newly opened file stream is not positioned at the beginning of the file.");
                    Assert.AreNotEqual(0, mpqStream.Length, "Opened file stream has zero size.");
                }
            }
        }

        [Test]
        public void MpqStreamPositionTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                using (var mpqFile = mpqArchive.OpenFile(mpqFilePath))
                using (var mpqStream = mpqFile.GetStream())
                {
                    mpqStream.Position = 1024;
                    Assert.AreEqual(1024, mpqStream.Position, "File stream is incorrectly positioned after setting position explicitly.");
                }
            }
        }

        [Test]
        public void MpqStreamSeekTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                using (var mpqFile = mpqArchive.OpenFile(mpqFilePath))
                using (var mpqStream = mpqFile.GetStream())
                {
                    mpqStream.Seek(4096, SeekOrigin.Begin);
                    Assert.AreEqual(4096, mpqStream.Position, "File stream is incorrectly positioned after seeking from SeekOrigin.Begin.");
                    mpqStream.Seek(-2048, SeekOrigin.Current);
                    Assert.AreEqual(2048, mpqStream.Position, "File stream is incorrectly positioned after seeking from SeekOrigin.Current");
                    mpqStream.Seek(-1024, SeekOrigin.End);
                    Assert.AreEqual(mpqStream.Length - 1024, mpqStream.Position, "File stream is incorrectly positioned after seeking from SeekOrigin.End");
                }
            }
        }

        [Test]
        public void MpqStreamReadTest()
        {
            using (var mpqArchive = new MpqArchive(mpqArchivePath))
            {
                using (var mpqFile = mpqArchive.OpenFile(mpqFilePath))
                using (var mpqStream = mpqFile.GetStream())
                {
                    var buffer = new byte[1024];

                    int bytesRead = mpqStream.Read(buffer, 0, 1024);
                    Assert.AreEqual(1024, bytesRead, "File stream read less bytes that intended.");
                    Assert.AreEqual(1024, mpqStream.Position, "File stream position returned incorrect value.");
                }
            }
        }
    }
}